﻿using System;
using System.Drawing;
using System.Windows.Forms;

namespace ThreadSafeControls {
    public partial class ThreadSafeControl<TControl> : ThreadSafeControl where TControl : Control {

        protected readonly TControl _control;

        internal ThreadSafeControl(TControl control) : base(control) {
            _control = control;
        }

        internal TControl Control {
            get { return _control; }
        }

        public AnchorStyles Anchor {
            get { return ReturnAsync<AnchorStyles>(c => c.Anchor); }
            set { UpdateAsync(c => c.Anchor = value); }
        }

        public Color BackColor {
            get { return ReturnAsync<Color>(c => c.BackColor); }
            set { UpdateAsync(c => c.BackColor = value); }
        }

        public int Bottom {
            get { return ReturnAsync<int>(c => c.Bottom); }
        }

        public DockStyle Dock {
            get { return ReturnAsync<DockStyle>(c => c.Dock); }
            set { UpdateAsync(c => c.Dock = value); }
        }

        public Font Font {
            get { return ReturnAsync<Font>(c => c.Font); }
            set { UpdateAsync(c => c.Font = value); }
        }

        public Color ForeColor {
            get { return ReturnAsync<Color>(c => c.ForeColor); }
            set { UpdateAsync(c => c.ForeColor = value); }
        }

        public int Height {
            get { return ReturnAsync<int>(c => c.Height); }
            set { UpdateAsync(c => c.Height = value); }
        }

        public int Left {
            get { return ReturnAsync<int>(c => c.Left); }
            set { UpdateAsync(c => c.Left = value); }
        }

        public Point Location {
            get { return ReturnAsync<Point>(c => c.Location); }
            set { UpdateAsync(c => c.Location = value); }
        }

        public int Right {
            get { return ReturnAsync<int>(c => c.Right); }
        }

        public Size Size {
            get { return ReturnAsync<Size>(c => c.Size); }
            set { UpdateAsync(c => c.Size = value); }
        }

        public object Tag {
            get { return ReturnAsync<object>(c => c.Tag); }
            set { UpdateAsync(c => c.Tag = value); }
        }

        public string Text {
            get { return ReturnAsync<string>(c => c.Text); }
            set { UpdateAsync(c => c.Text = value); }
        }

        public int Top {
            get { return ReturnAsync<int>(c => c.Top); }
            set { UpdateAsync(c => c.Top = value); }
        }

        public bool Visible {
            get { return ReturnAsync<bool>(c => c.Visible); }
            set { UpdateAsync(c => c.Visible = value); }
        }

        public int Width {
            get { return ReturnAsync<int>(c => c.Width); }
            set { UpdateAsync(c => c.Width = value); }
        }

        internal void UpdateAsync(Action<TControl> action) {
            if (_control.InvokeRequired)
                _control.BeginInvoke(action, _control);
            else
                action(_control);
        }

        internal T ReturnAsync<T>(Func<TControl, T> func) {
            if (_control.InvokeRequired)
                return (T)_control.Invoke(func, _control);
            else
                return func(_control);
        }
    }
}
